﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Threading;
using System.IO; // test

using RAFOJ.Structs;

namespace RAFOJ.Submitters
{
    abstract class Submitter
    {
        protected int NumberOfUsernames;
        protected Submission []submissions;
        protected HttpWebRequest[] httpRequests;
        protected bool[] used;
        protected string[] usernames;
        protected string[] passwords;
        protected CookieContainer[] cookies;

        // Constructors
        public Submitter() { }

        public Submitter(string judgeName)
        {
            // Ucitaj usernames iz baze na osnovu judgeName
            NumberOfUsernames = 2;

            // Declare arrays of length NumberOfUsernames for each variable
            submissions = new Submission[NumberOfUsernames];
            httpRequests = new HttpWebRequest[NumberOfUsernames];
            used = new bool[NumberOfUsernames];
            usernames = new string[NumberOfUsernames];
            passwords = new string[NumberOfUsernames];
            cookies = new CookieContainer[NumberOfUsernames];

            used[0] = true;
            used[1] = false;
            if (judgeName == "SPOJ")
            {
                usernames[1] = "montano";
                passwords[1] = "montanovpass";
            }
            else if (judgeName == "Timus")
            {
                usernames[1] = "130759BW";
            }
        }

        // Methods

        /**
         * Waits for usernames[idx] to be unfrozen (to set used[idx] to false) for waitTime milliseconds.
         **/

        protected void waitForUnfreeze(int idx, int waitTime)
        {
            Console.WriteLine("Unfreezing account " + usernames[idx] + "...");
            Thread.Sleep(waitTime);
            if (httpRequests[idx] != null) httpRequests[idx].Abort();
            httpRequests[idx] = null;
            used[idx] = false;
            Console.WriteLine("Unfreezed account " + usernames[idx] + "...");
        }

        /**
         * Updates standings in datebase based on submissions[idx]
         **/
        protected void updateStandings(int idx)
        {
            Console.WriteLine("Updating standings...");
            Console.WriteLine("Result for " + usernames[idx] + ": " + submissions[idx].getStatus());
            if (submissions[idx].getStatus() == "Compilation error")
            {
                Console.WriteLine();
                Console.WriteLine(submissions[idx].getErrorInfo());
                Console.WriteLine();
                StreamWriter sr = new StreamWriter("SPOJCE.html");
                sr.WriteLine(submissions[idx].getErrorInfo());
                sr.Close();
            }
            // Needs implementation
        }

        /**
         * Returns index of username that can be used to submit submission.
         **/
        protected int getIdleClient()
        {
            const int waitInterval = 500;

            while (true)
            {
                for (int i = 0; i < NumberOfUsernames; i++)
                {
                    if (!used[i])
                    {
                        used[i] = true;
                        Console.WriteLine("Using account: " + usernames[i] + "...");
                        return i;
                    }
                }
                Thread.Sleep(waitInterval);
            }
        }

        /**
         * Returns url with data parameters that has to be sent
         **/ 
        protected string createPostData(string[] data)
        {
            if (data.Length == 0) return "";

            string postData = data[0];

            for (int i = 1; i < data.Length; i++)
            {
                postData += "&" + data[i];
            }

            return postData;
        }

        /**
         * Creates httpRequests[idx] and submits it with the given url and postData
         */

        protected string createHttpRequest(int idx, string postData, string url, bool saveCookies = false)
        {
            Console.WriteLine("Creating http request for account " + usernames[idx] + "...");

            // Create new http request and set method to POST
            httpRequests[idx] = (HttpWebRequest)WebRequest.Create(url);
            httpRequests[idx].Method = "POST";

            byte[] byteArray = Encoding.UTF8.GetBytes(postData);

            // Set the ContentType property of the WebRequest.
            httpRequests[idx].ContentType = "application/x-www-form-urlencoded";
            httpRequests[idx].ContentLength = byteArray.Length;

            // Get the request stream.
            Stream dataStream = httpRequests[idx].GetRequestStream();
            dataStream.Write(byteArray, 0, byteArray.Length);
            dataStream.Close();

            // Get the response and cookies.
            if (saveCookies)
            {
                cookies[idx] = new CookieContainer();
                httpRequests[idx].CookieContainer = cookies[idx];
            }
            
            HttpWebResponse response = (HttpWebResponse)httpRequests[idx].GetResponse();
            
            if (saveCookies) cookies[idx] = httpRequests[idx].CookieContainer;

            Stream dataStream2 = response.GetResponseStream();

            // Open the stream using a StreamReader for easy access.
            StreamReader reader2 = new StreamReader(dataStream2);

            // Read the content.
            string responseFromServer = reader2.ReadToEnd();
            
            response.Close();

            // Return response from server
            return responseFromServer;
        }
    }
}
